package cn.krui.helper.tools;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author zc
 */
public class MapModelUtils {
  private Map<String, Object> data = new LinkedHashMap<>();
  
  public MapModelUtils() {}
  
  public MapModelUtils(String propName1, Object propValue1) {
    this();
    this.data.put(propName1, propValue1);
  }
  
  public MapModelUtils(String propName1, Object propValue1, String propName2, Object propValue2) {
    this(propName1, propValue1);
    this.data.put(propName2, propValue2);
  }
  
  public MapModelUtils(String propName1, Object propValue1, String propName2, Object propValue2, String propName3, Object propValue3) {
    this(propName1, propValue1, propName2, propValue2);
    this.data.put(propName3, propValue3);
  }
  
  public MapModelUtils(String propName1, Object propValue1, String propName2, Object propValue2, String propName3, Object propValue3, String propName4, Object propValue4) {
    this(propName1, propValue1, propName2, propValue2, propName3, propValue3);
    this.data.put(propName4, propValue4);
  }
  
  public MapModelUtils(String propName1, Object propValue1, String propName2, Object propValue2, String propName3, Object propValue3, String propName4, Object propValue4, String propName5, Object propValue5) {
    this(propName1, propValue1, propName2, propValue2, propName3, propValue3, propName4, propValue4);
    this.data.put(propName5, propValue5);
  }
  
  public MapModelUtils(String propName1, Object propValue1, String propName2, Object propValue2, String propName3, Object propValue3, String propName4, Object propValue4, String propName5, Object propValue5, String propName6, Object propValue6) {
    this(propName1, propValue1, propName2, propValue2, propName3, propValue3, propName4, propValue4, propName5, propValue5);
    this.data.put(propName6, propValue6);
  }
  
  public MapModelUtils add(String propertyName, Object propertyValue) {
    this.data.put(propertyName, propertyValue);
    return this;
  }
  
  public MapModelUtils add(Map<String, Object> d) {
    this.data.putAll(d);
    return this;
  }
  
  public MapModelUtils add(Object obj) {
    add(JsonUtils.toObject(JsonUtils.toJson(obj)));
    return this;
  }
  
  public MapModelUtils remove(String propertyName) {
    this.data.remove(propertyName);
    return this;
  }
  
  public Object getValue(String propertyName) {
    return this.data.get(propertyName);
  }
  
  public MapModelUtils clear() {
    this.data.clear();
    return this;
  }
  
  public Map<String, Object> getValues() {
    return this.data;
  }
  
  public MapModelUtils fillObject(Object obj) {
    if (obj != null) {
      Class<?> type = obj.getClass();
      byte b;
      int i;
      Field[] arrayOfField;
      for (i = (arrayOfField = type.getDeclaredFields()).length, b = 0; b < i; ) {
        Field field = arrayOfField[b];
        if (this.data.containsKey(field.getName())){
          try {
            field.setAccessible(true);
            field.set(obj, this.data.get(field.getName()));
          } catch (Throwable throwable) {} 
        }
        b++;
      } 
      for (i = (arrayOfField = type.getFields()).length, b = 0; b < i; ) {
        Field field = arrayOfField[b];
        if (this.data.containsKey(field.getName())){
          try {
            field.setAccessible(true);
            field.set(obj, this.data.get(field.getName()));
          } catch (Throwable throwable) {} 
        }
        b++;
      } 
      Method[] arrayOfMethod;
      for (i = (arrayOfMethod = type.getDeclaredMethods()).length, b = 0; b < i; ) {
        Method method = arrayOfMethod[b];
        if (method.getParameterCount() == 1 && 
          method.getName().startsWith("set")) {
          String name = method.getName().substring(3);
          try {
            Object val = this.data.get(name);
            if (this.data != null && this.data.getClass().isAssignableFrom(method.getParameterTypes()[0])){
              method.invoke(obj, new Object[] { val }); 
            }
          } catch (Throwable throwable) {}
        } 
        b++;
      } 
      for (i = (arrayOfMethod = type.getMethods()).length, b = 0; b < i; ) {
        Method method = arrayOfMethod[b];
        if (method.getParameterCount() == 1 && 
          method.getName().startsWith("set")) {
          String name = method.getName().substring(3);
          try {
            Object val = this.data.get(name);
            if (this.data != null && 
              this.data.getClass().isAssignableFrom(method.getParameterTypes()[0])){
                method.invoke(obj, new Object[] { val }); 
              }
          } catch (Throwable throwable) {}
        } 
        b++;
      } 
    } 
    return this;
  }
}
